package com.yundasys.lab17.lab17springbootdemo.excel;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;

/**
 * @PACKAGE_NAME: com.yundasys.lab17.lab17springbootdemo.excel
 * @NAME: Excel
 * @USER: jiangta
 * @DATE: 2022/11/30
 * @TIME: 5:03 下午
 * @PROJECT_NAME: springboot-labs
 */
public class Excel {

    /**
     * 读取excel并转换为表实体
     *
     * @param excelPath
     * @return
     */
    public TableEntity readExcel(String excelPath) {
        // 解析模板对象List
        List<ColumnEntity> entities = new ArrayList<ColumnEntity>();
        // 表物理名
        String physicalTableName = null;
        // 表逻辑名
        String logicalTableName = null;
        // 数据库名
        String databaseName = null;
        try {
            // String encoding = "GBK";
            File excel = new File(excelPath);
            if (excel.isFile() && excel.exists()) { // 判断文件是否存在

                String[] split = excel.getName().split("\\."); // .是特殊字符，需要转义！！！！！
                Workbook wb;
                // 根据文件后缀（xls/xlsx）进行判断
                if ("xls".equals(split[1])) {
                    FileInputStream fis = new FileInputStream(excel); // 文件流对象
                    wb = new HSSFWorkbook(fis);
                } else if ("xlsx".equals(split[1])) {
                    wb = new XSSFWorkbook(excel);
                } else {
                    System.out.println("文件类型错误!");
                    return null;
                }

                // 开始解析
                Sheet sheet = wb.getSheetAt(0); // 读取sheet 0

                int firstRowIndex = sheet.getFirstRowNum() + 2; // 第一、二行是列名，所以不读，从第三行开始读
                int lastRowIndex = sheet.getLastRowNum();
                // System.out.println("firstRowIndex: "+firstRowIndex);
                // System.out.println("lastRowIndex: "+lastRowIndex);

                // 解析模板对象List
                entities = new ArrayList<ColumnEntity>();
                // 数据库名
                databaseName = sheet.getRow(0).getCell(1).getStringCellValue();
                // 表物理名
                physicalTableName = sheet.getRow(0).getCell(3).getStringCellValue();
                // 表逻辑名
                logicalTableName = sheet.getRow(0).getCell(5).getStringCellValue();

                for (int rIndex = firstRowIndex; rIndex <= lastRowIndex; rIndex++) { // 遍历行
                    // System.out.println("rIndex: " + rIndex);
                    ColumnEntity entity = new ColumnEntity();
                    Row row = sheet.getRow(rIndex);
                    if (row != null) {
                        if (row.getCell(0, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue() == null || row
                                .getCell(0, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue().isEmpty()) {
                            continue;
                        }
                        /*
                         * int firstCellIndex = row.getFirstCellNum(); int lastCellIndex =
                         * row.getLastCellNum(); for (int cIndex = firstCellIndex; cIndex <
                         * lastCellIndex; cIndex++) { //遍历列 Cell cell = row.getCell(cIndex); if (cell !=
                         * null) { System.out.println(cell.toString()); } }
                         */

                        // 解析对象
                        entity.setPhysicalColumnName(
                                row.getCell(0, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue());// 列物理名
                        entity.setLogicalColumnName(
                                row.getCell(1, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue());// 列逻辑名
                        entity.setType(row.getCell(2, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue());// 类型
                        entity.setLength(String.valueOf(row.getCell(3, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue()));// 长度
                        entity.setDecimal(String.valueOf(row.getCell(4, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue()));// 精度
                        entity.setPrimaryKey(row.getCell(5, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue());// 是否主键
                        entity.setNotNull(row.getCell(6, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue());// 是否非空
                        // 存入list
                        entities.add(entity);
                    }
                }
            } else {
                System.out.println("找不到指定的文件");
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        TableEntity tableEntity = new TableEntity();
        tableEntity.setEntities(entities);
        tableEntity.setDatabaseName(databaseName);
        tableEntity.setLogicalTableName(logicalTableName);
        tableEntity.setPhysicalTableName(physicalTableName);
        return tableEntity;
    }

    /**
     * 将表实体转换为sql并输出为txt
     *
     * @param tableEntity
     */
    public void convertSQL(TableEntity tableEntity) {
        StringBuffer sql = new StringBuffer();
        sql.append("CREATE TABLE `");
        sql.append(tableEntity.getDatabaseName());
        sql.append("`.`");
        sql.append(tableEntity.getPhysicalTableName());
        sql.append("` (");
        // CREATE TABLE `databaseName`.`tablePhysicalName` (
        List<ColumnEntity> cellEnties = tableEntity.getEntities();
        // 主键
        String primaryKey = null;
        // 获取主键
        for (ColumnEntity item : cellEnties) {
            // 将pk为true的设为主键
            if ("*".equals(item.getPrimaryKey())) {
                primaryKey = item.getPhysicalColumnName();
                break;
            }
        }
        // 循环列
        for (ColumnEntity item : cellEnties) {
            sql.append(" `");
            sql.append(item.getPhysicalColumnName().trim());
            sql.append("` ");
            // `physicalColumnName`

            // 根据NOT NULL 来拼接
            if ("*".equals(item.getNotNull())) { // 如果不允许为空，则拼接NOT NULL
                //类型
                String type = item.getType().toLowerCase();
                //类型转换
                if (type.indexOf("varchar") != -1) {
                    type = TableTypeConstant.VARCHAR;
                } else if (type.indexOf("number") != -1) {
                    type = TableTypeConstant.INT;
                    //默认长度
                    if (item.getLength() == null || item.getLength().isEmpty()) {
                        item.setLength("11");
                    }
                } else if (type.indexOf("char") != -1) {
                    type = TableTypeConstant.CHAR;
                } else if (type.indexOf("bigint") != -1) {
                    type = TableTypeConstant.BIG_INT;
                    //默认长度
                    if (item.getLength() == null || item.getLength().isEmpty()) {
                        item.setLength("20");
                    }
                } else if (type.indexOf("tinyint") != -1) {
                    type = TableTypeConstant.TINY_INT;
                    //默认长度
                    if (item.getLength() == null || item.getLength().isEmpty()) {
                        item.setLength("4");
                    }
                } else if (type.indexOf("decimal") != -1) {
                    type = TableTypeConstant.DECIMAL;
                }


                // 根据类型选择是否拼接长度
                if (TableTypeConstant.CHAR.equals(type) || TableTypeConstant.VARCHAR.equals(type)) { // 文本需要拼接长度
                    sql.append(type);
                    sql.append("(");
                    sql.append(item.getLength());
                    sql.append(") CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '");
                } else if (TableTypeConstant.TEXT.equals(type) || TableTypeConstant.LONG_TEXT.equals(type)) { // 文本不需要拼接长度
                    sql.append(type);
                    sql.append(" CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '");
                } else if (TableTypeConstant.DATE.equals(type)) { // 时间不需要拼接长度
                    sql.append(type);
                    sql.append(" NOT NULL COMMENT '");
                } else if (TableTypeConstant.DATE_TIME.equals(type) || TableTypeConstant.TIME_STAMP.equals(type)) { // 时间需要拼接长度 并且长度为0
                    sql.append(type);
                    sql.append("(0) NOT NULL COMMENT '");
                } else if (TableTypeConstant.INT.equals(type) || TableTypeConstant.BIG_INT.equals(type) || TableTypeConstant.TINY_INT.equals(type)) { // 数字需要拼接长度
                    sql.append(type);
                    sql.append("(");
                    sql.append(item.getLength());
                    sql.append(")  NOT NULL COMMENT '");
                } else if (TableTypeConstant.DECIMAL.equals(type) ) { // 数字需要拼接长度
                    sql.append(type);
                    sql.append("(");
                    sql.append(item.getLength());
                    sql.append(",").append(item.getDecimal());
                    sql.append(")  NOT NULL COMMENT '");
                }
            } else { // 如果允许为空，则拼接 NULL DEFAULT NULL

                String type = item.getType().toLowerCase();
                //类型转换
                if (type.indexOf("varchar") != -1) {
                    type = TableTypeConstant.VARCHAR;
                } else if (type.indexOf("number") != -1) {
                    type = TableTypeConstant.INT;
                    //默认长度
                    if (item.getLength() == null || item.getLength().isEmpty()) {
                        item.setLength("11");
                    }
                } else if (type.indexOf("char") != -1) {
                    type = TableTypeConstant.CHAR;
                } else if (type.indexOf("bigint") != -1) {
                    type = TableTypeConstant.BIG_INT;
                    //默认长度
                    if (item.getLength() == null || item.getLength().isEmpty()) {
                        item.setLength("20");
                    }
                } else if (type.indexOf("tinyint") != -1) {
                    type = TableTypeConstant.TINY_INT;
                    //默认长度
                    if (item.getLength() == null || item.getLength().isEmpty()) {
                        item.setLength("4");
                    }
                } else if (type.indexOf("decimal") != -1) {
                    type = TableTypeConstant.DECIMAL;
                }

                // 根据类型选择是否拼接长度
                if (TableTypeConstant.CHAR.equals(type) || TableTypeConstant.VARCHAR.equals(type)) { // 文本需要拼接长度
                    sql.append(type);
                    sql.append("(");
                    sql.append(item.getLength());
                    sql.append(") CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '");
                } else if (TableTypeConstant.TEXT.equals(type) || TableTypeConstant.LONG_TEXT.equals(type)) { // 文本不需要拼接长度
                    sql.append(type);
                    sql.append(" CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '");
                } else if (TableTypeConstant.DATE.equals(type)) { // 时间不需要拼接长度
                    sql.append(type);
                    sql.append(" NULL DEFAULT NULL COMMENT '");
                } else if (TableTypeConstant.DATE_TIME.equals(type) || TableTypeConstant.TIME_STAMP.equals(type)) { // 时间需要拼接长度 并且长度为0
                    sql.append(type);
                    sql.append("(0) NULL DEFAULT NULL COMMENT '");
                } else if (TableTypeConstant.INT.equals(type) || TableTypeConstant.BIG_INT.equals(type) || TableTypeConstant.TINY_INT.equals(type)) { // 数字需要拼接长度
                    sql.append(type);
                    sql.append("(");
                    sql.append(item.getLength());
                    sql.append(")  NULL DEFAULT NULL COMMENT '");
                } else if (TableTypeConstant.DECIMAL.equals(type) ) { // 数字需要拼接长度
                    sql.append(type);
                    sql.append("(");
                    sql.append(item.getLength());
                    sql.append(",").append(item.getDecimal());
                    sql.append(")  NULL COMMENT '");
                }
            }

            // 拼接逻辑列名
            sql.append(item.getLogicalColumnName());
            sql.append("',");
            sql.append("\r\n");
        }

        // 拼接主键
        sql.append(" PRIMARY KEY (`");
        sql.append(primaryKey);
        sql.append("`) USING BTREE ) ");
        // 拼接引擎和逻辑表名
        sql.append("ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '");
        sql.append(tableEntity.getLogicalTableName());
        //sql.append("'  ROW_FORMAT = Compact;");
        sql.append("';");
        System.err.println(sql);
        try {
            writeTXT("", sql.toString(), tableEntity.getPhysicalTableName() + tableEntity.getLogicalTableName());
            System.out
                    .println("已导出:" + tableEntity.getPhysicalTableName() + tableEntity.getLogicalTableName() + ".txt!");
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("导出文件失败");
        }
    }

    /**
     * 将字符串写入txt并导出
     *
     * @throws Exception
     */
    public void writeTXT(String path, String value, String fileName) throws Exception {
        File f = new File(path + fileName + ".txt");
        FileOutputStream fos1 = new FileOutputStream(f);
        OutputStreamWriter dos1 = new OutputStreamWriter(fos1);
        dos1.write(value);
        dos1.close();
    }
}
